package sample.web.controller;

import com.amazonaws.SdkClientException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import sample.web.config.S3Config;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;


/**
 * <p>Class       : app.controller.IndexLoginController
 * <p>Descdription: 首页和登录控制逻辑的统一处理
 *
 * @author  gulixing@msn.com
 * @version 1.0.0
 */
@Controller
public class DownloadController{
    /**
     * Logger for this class
     */
    private static final Logger logger = LoggerFactory.getLogger(DownloadController.class);

	@RequestMapping(value = "/download", method = RequestMethod.GET)
	public void download(HttpServletRequest request, HttpServletResponse response, @RequestParam String fileKey) throws Exception {
		logger.info("key:{}",fileKey);
		S3Object object = getObjectByKey(fileKey);
		if(object!=null){
	       //对数据库中有内容但磁盘文件无法访问的情况给出明确的用户提示
		   makeDownload(request,response,object);
		}
        //如果无法根据fileId从数据库中找到记录说明客户端手动修改了fileId
		//此种情况属于非正常行为，不做特殊处理
		return;
	}

	public S3Object getObjectByKey(String fileKey) {
		AmazonS3 conn = S3Config.getAmazonS3();
		S3Object object = null;
		try {
			object = conn.getObject(new GetObjectRequest(S3Config.bucket_name, fileKey));
		} catch (SdkClientException e) {
            logger.error("文件不存在！",e.getCause());
			return null;
		}
		if (object != null) {
			//将上传了的文件生成一个url连接，可以直接通过url连接访问文件
			GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(S3Config.bucket_name, object.getKey());
			URL url = conn.generatePresignedUrl(urlRequest);
			logger.info("url:{}", url);
			ObjectMetadata metadata = object.getObjectMetadata();
			logger.info(metadata.getUserMetaDataOf("name"));
			logger.info(metadata.getUserMetaDataOf("user"));
			return object;
		}
		return null;
	}

	private static void makeDownload(HttpServletRequest request,
									HttpServletResponse response, S3Object object) throws
			IOException {
		ObjectMetadata metadata = object.getObjectMetadata();
		response.setContentType("text/html;charset=UTF-8");
		request.setCharacterEncoding("UTF-8");
		String contentType = "application/octet-stream";
		response.setContentType(contentType);
		response.setHeader("Content-disposition", "attachment; filename=" + processFileName(request, object));
		response.setHeader("Content-Length", String.valueOf(object.getObjectMetadata().getContentLength()));
		BufferedOutputStream bos = null;
		BufferedInputStream bis = new BufferedInputStream(object.getObjectContent());
		try {
			bos = new BufferedOutputStream(response.getOutputStream());
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (IOException e) {
			logger.error("下载文件处理异常",e);
		} finally{
			bis.close();
			bos.close();
		}
	}

	/**
	 * <p>Method ：processFileName
	 * <p>Description : 识别浏览器类型，避免文件名中文乱码问题
	 * @param request
	 * @return
	 * @throws UnsupportedEncodingException
	 * @author  gulixing@msn.com
	 * @version 1.0.0
	 */
	private static String processFileName(HttpServletRequest request,S3Object object) throws UnsupportedEncodingException{
		String agent = request.getHeader("USER-AGENT");
		String metaName = object.getObjectMetadata().getUserMetadata().get("name");
		//优先读取元数据中的文件名，如果为空则读取fileKey后缀
        String fileName = Strings.isNotEmpty(metaName)?metaName: StringUtils.substringAfterLast(object.getKey(),"/");
		String enableFileName;
		if(agent != null && !agent.contains("MSIE")) {// FF
			enableFileName = "=?UTF-8?B?" + (new String(Base64.encodeBase64(fileName.getBytes("UTF-8")))) + "?=";
		} else { // IE
			enableFileName = new String(fileName.getBytes("GBK"), "ISO-8859-1");
		}
		return enableFileName;
	}
}